package managers.popupManager;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import managers.OptionsManager;
import utils.StackTracePrinter;

public class PopupManager extends ComponentAdapter implements Runnable {

	
	private static final int START_BAR_HEIGHT = 40;

	private static PopupManager sharedInstance = new PopupManager();

	private static final int DEFAULT_VERTICAL_SPACING = 122;
	private static final int DEFAULT_POPUP_LIFE = 8000;

	public static final int INFORMATION_POPUP = 0;
	public static final int CONFIRM_POPUP = 1;

	private boolean[] currentlyDisplayedDialogs = new boolean[5];
	private Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
	
	private int offsetFromBaseline = START_BAR_HEIGHT;
	private int verticalSpacing = DEFAULT_VERTICAL_SPACING;
	private int popupLife = DEFAULT_POPUP_LIFE;
	private PopupFactory factory;
	

	private List<Dialog> dialogPool = Collections.synchronizedList(new LinkedList<Dialog>());
	private List<Dialog> dialogQueue = Collections.synchronizedList(new LinkedList<Dialog>());

	private Properties options = OptionsManager.getSharedInstance().getOptionGroup("soundPopup");
	private HashMap<String, Object[]> messages = new HashMap<String, Object[]>();

	private boolean parametersSet = false;


	private PopupManager () {
	}

	public void setParameters (PopupFactory factory, int verticalSpacing, int offsetfromBaseline, int popupLife) {
		this.popupLife = popupLife;
		this.verticalSpacing = verticalSpacing;
		this.offsetFromBaseline = offsetfromBaseline;
		this.factory = factory;
		parametersSet = true;
	}
	
	public void setParameters (PopupFactory factory) {
		this.factory = factory;
		parametersSet = true;
	}
	
	public void putMessage (String name, Object[] messageAndIconURL) {
		messages.put(name, messageAndIconURL);
	}
	
	private Dialog getInformationDialog (String eventType) {
		if (dialogPool.size() == 0) {
			return factory.createInformationDialog(this, popupLife, eventType);
		} else
			return dialogPool.remove(0);
	}

	private synchronized int incrementCount () {
		boolean free = false;
		int index = 0;
		for (int i = 0; i< currentlyDisplayedDialogs.length; i++) {
			if (currentlyDisplayedDialogs[i] == false) {
				free = true;
				currentlyDisplayedDialogs[i] = true;
				index = i;
				break;
			}
		}
		if (free == false) {
			try {
				wait();
			} catch (InterruptedException e) {
				StackTracePrinter.print(e);
			}
			index = incrementCount();
		}
		return index;
	}
	private synchronized void decrementCount (int index) {
		notify();
		currentlyDisplayedDialogs[index] = false;
	}

	public void preparePopup (String name, int popupType, String eventType, ActionListener okAction) {
		if (parametersSet  == false) {
			throw new IllegalArgumentException("Popup manager parameters not set");
		}
		if (options.getProperty(eventType+".POPUP") == null) {
			throw new IllegalArgumentException("Not available event.");
		}
		if (options.getProperty(eventType+".POPUP").equals("false"))
			return;
		Dialog dialog = null;
		Object[] data = messages.get(eventType);
		if (popupType == INFORMATION_POPUP) {
			dialog = getInformationDialog(eventType);
			dialog.setIcon(PopupManager.class.getResource("/images/others/photo_mini.png"));
		} else  if (popupType == CONFIRM_POPUP) {
			dialog = factory.createConfirmDialog(okAction, this, 0, eventType);
			dialog.setIcon(PopupManager.class.getResource("/images/others/image.png"));
		}
		if (data[1] != null) {
			dialog.setIcon((URL)data[1]);
		} else {
			dialog.setIcon(PopupManager.class.getResource("/images/others/photo_mini.png"));
		}
		if (data[0] != null)
			dialog.setText(name, (String)data[0]);
		
		if (options.getProperty(eventType+".SOUND").equals("true"))
		addToQueue(dialog);
	}


	private void addToQueue(Dialog dialog) {
		dialogQueue.add(dialog);
		if (dialogQueue.size() == 1) {
			new Thread(this).start();
		}
	}

	public static PopupManager getSharedInstance () {
		return sharedInstance;
	}

	@Override
	public void run() {
		while (dialogQueue.size() != 0) {
			InformationDialog dialog = (InformationDialog)dialogQueue.remove(0);
			int index = incrementCount();
			dialog.setIndex(index);
			dialog.setLocation(screenDimension.width-dialog.getWidth(), screenDimension.height-verticalSpacing*dialog.getIndex()-dialog.getHeight()-offsetFromBaseline);
			if (dialog instanceof Timed) {
				((Timed) dialog).startTimer();
			}
			dialog.setVisible(true);
			dialog.playSound();
		}

	}
	
	@Override
	public void componentHidden(ComponentEvent e) {
		Dialog temp =(Dialog) e.getSource();
		decrementCount(temp.getIndex());
	}

}